﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;
using Yala.Core.Authentication;
using Moq;
using Yala.Client.Web.MVC.Controllers;
using StructureMap;
using Yala.Models.Users;
using Yala.UnitTests.FakeDependencies.Repositories;
using Yala.UnitTests.FakeDependencies.Authentication;
using Yala.Models.AuthProviders;
using System.Web.Mvc;

namespace Yala.UnitTests.Test.Controllers {
    [TestFixture]
    public class OpenIdAccountControllerTest {

        IFormsAuthentication _formsAuth;
        IUsersRepository _usersRepo;
        IAuthProvidersRepository _authProviderRepo;
        OpenIdAccountController _openIdAccountController;

        [TestFixtureSetUp]
        public void Init() {
            var formsAuth = new Mock<IFormsAuthentication>();
            formsAuth.Setup(x => x.SignIn(It.IsAny<Guid>(), It.IsAny<string>(), It.IsAny<bool>()));
            _formsAuth = formsAuth.Object;
        }

        [SetUp]
        public void SetUp() {
            _usersRepo = new FakeUsersRepository();
            _authProviderRepo = new FakeAuthProvidersRepository();
            _openIdAccountController = new OpenIdAccountController(_usersRepo, _authProviderRepo, _formsAuth, new FakeMembership());
            //Create a fake google url            
            _authProviderRepo.Add(new AuthProvider {
                Name = "google",
                ServiceUrl = "fakeurl.com"
            });
        }

        [Test]
        public void LogOn_User_Can_Access_Profile_Page_When_Authenticated() {
            ActionResult results = _openIdAccountController.LogOn();

            Assert.IsNotNull(results);
            Assert.IsInstanceOf(typeof(RedirectToRouteResult), results);

            var typedResults = results as RedirectToRouteResult;
            Assert.AreEqual("Profile", typedResults.RouteValues["action"], "Wrong action");
            Assert.AreEqual("Account", typedResults.RouteValues["controller"], "Wrong controller");
        }

        [Test]
        public void LogOn_User_Not_Authenticated_Should_Be_Redirect_To_Index() {

            // We need to false the membership api to fail
            var authProvider = _authProviderRepo.Single(x => x.Name.Contains("google"));
            authProvider.ServiceUrl = "badServiceUrl";
            _authProviderRepo.Update(authProvider);

            ActionResult results = _openIdAccountController.LogOn();

            Assert.IsNotNull(results);
            Assert.IsInstanceOf(typeof(RedirectToRouteResult), results);

            var typedResults = results as RedirectToRouteResult;
            Assert.AreEqual("Index", typedResults.RouteValues["action"], "Wrong action");
            Assert.AreEqual("Home", typedResults.RouteValues["controller"], "Wrong controller");
        }

        [Test]
        public void LogOn_First_Time_User_Should_Be_Registered() {
            Assert.AreEqual(0, _usersRepo.All().Count());
            ActionResult results = _openIdAccountController.LogOn();
            Assert.AreEqual(1, _usersRepo.All().Count());
        }

        [Test]
        public void LogOn_Existing_User_Should_Be_Updated() {
            //Create an existing user
            var lastUpdatedDate = Convert.ToDateTime("06/19/2011 00:15:32.000");
            var openId = "https://www.google.com/accounts/o8/id?id=foo";

            _usersRepo.Add(new User {
                LastLogOnDate = lastUpdatedDate,
                OpenId = openId,
            });

            Assert.AreEqual(1, _usersRepo.All().Count());
            ActionResult results = _openIdAccountController.LogOn();

            Assert.AreEqual(1, _usersRepo.All().Count());
            var updatedUser = _usersRepo.Single(u => u.OpenId == openId);
            Assert.AreNotEqual(lastUpdatedDate, updatedUser.LastLogOnDate);
        }
    }
}
